﻿using System;
using System.Linq; 
using System.Collections.Generic;
using System.Runtime.Serialization;
using Sinacor.Infra.Service.Validation;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;

namespace Sinacor.Servico.Bovespa.Corretagem.BusinessLogic
{

    //Task  : 5617 
    // Data : 11/03/2009
    // Autor:Apsilva
    /// <summary>
    /// Bussiness Logic de Desconto
    /// </summary>
    public class Desconto: BaseBusinessLogic
    {

        #region Constantes de Erro

 
        private const int ERRO_DATAFINALMAIORDATAINICIAL = 109105;
        private const int ERRO_PERCENTUALACRESCIMO_MENOR = 109108;
        private const int ERRO_BUSSINESSENTITYDESCONTO_NULA = 109066;
        private const int ERRO_CONFLITONAOPERMITEAJUSTE = 109151;
        private const int ERRO_CONFLITONAOPERMITEAJUSTE_INCLUIR = 109152;
        private const int ERRO_EXISTENCIADESCONTO_INCLUIRAJUSTAR = 109241;
        private const int ERRO_EXISTENCIADESCONTO_INCLUIR = 109242;

        #endregion

        #region Construtor
        public Desconto()
            : base()
        {

        }
        #endregion


        #region Métodos

        /// <summary>
        /// Ajustar o Desconto para o Conflito Ocorrido
        /// </summary>
        /// <param name="DescontoConflito"></param>
        /// <param name="DescontoIncluido"></param>
        public void AjustarConflitoDesconto(BusinessEntity.Desconto DescontoConflito, BusinessEntity.Desconto DescontoIncluido )
        {
            ResourceAccess.Desconto desconto = new Sinacor.Servico.Bovespa.Corretagem.ResourceAccess.Desconto();
            DateTime dataAjuste =  DescontoIncluido.Periodo.DataInicial.Value.AddDays(-1) ; 
            desconto.AjustarConflitoDesconto(DescontoConflito, dataAjuste);
        }

        /// <summary>
        /// Retornar a Lista de Conflito para o Período
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public List<BusinessEntity.Desconto> ConsultarConflitoPeriodo(BusinessEntity.Desconto request)
        {
            return new ResourceAccess.Desconto().ConsultarConflitoPeriodo(request); 
        }


        /// <summary>
        /// Retornar a lista com  os Descontos apra o filtro
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public List<BusinessEntity.Desconto> ConsultarDescontos( BusinessEntity.Parameter.FiltroDescontoChave request)
        {
            return new ResourceAccess.Desconto().ConsultarDescontos(request); 
        }

        /// <summary>
        /// Excluir desconto a partir da chave
        /// </summary>
        /// <param name="request"></param>

        public void ExcluirDesconto(BusinessEntity.Parameter.FiltroDescontoChave request)
        {
             new ResourceAccess.Desconto().ExcluirDesconto(request); 
        }

        /// <summary>
        /// Excluir Lista de Descontos 
        /// </summary>
        /// <param name="request"></param>
        public void ExcluirDescontos(List<BusinessEntity.Parameter.FiltroDescontoChave> request)
        {
            foreach (BusinessEntity.Parameter.FiltroDescontoChave item in request)
            {
                ExcluirDesconto(item); 
            }

        }


        /// <summary>
        /// Incluir Ajuste de Desconto
        /// </summary>
        /// <param name="request"></param>
        public void IncluirAjustarDesconto(BusinessEntity.Desconto request)
        {
            if (request == null)
                throw new BusinessException(ERRO_BUSSINESSENTITYDESCONTO_NULA);

            ValidarDesconto(request);


            if(ValidarExistenciaDesconto(request.Periodo.DataInicial.Value))
                throw new BusinessException(ERRO_EXISTENCIADESCONTO_INCLUIRAJUSTAR);

            BusinessEntity.Conflito conflito =  VerificarConflitoPeriodo(request);


            if (conflito.ExisteConflito)
            {

                if (conflito.PermiteAjuste)
                {
                    List<BusinessEntity.Desconto> ajuste = ConsultarConflitoPeriodo(request);
                    AjustarConflitoDesconto(ajuste[0], request); 

                }

                else

                    throw new ValidationException(ERRO_CONFLITONAOPERMITEAJUSTE);

            }
            //new ResourceAccess.Desconto().
            IncluirDesconto(request);
                
        }


        /// <summary>
        /// Incluir Desconto
        /// Task 6026 - Alteração do método, inclusão de verificações - LLiez.7comm
        /// </summary>
        /// <param name="request"></param>
        public void IncluirDesconto(BusinessEntity.Desconto request)
        {
            if (request == null)
                throw new BusinessException(ERRO_BUSSINESSENTITYDESCONTO_NULA);

            ValidarDesconto(request);


            if (ValidarExistenciaDesconto(request.Periodo.DataInicial.Value))
                throw new BusinessException(ERRO_EXISTENCIADESCONTO_INCLUIR);


            BusinessEntity.Conflito conflito = VerificarConflitoPeriodo(request);


            if (conflito.ExisteConflito)
            {

                if (conflito.PermiteAjuste)
                {
                    List<BusinessEntity.Desconto> ajuste = ConsultarConflitoPeriodo(request);
                    AjustarConflitoDesconto(ajuste[0], request);

                }

                else

                    throw new ValidationException(ERRO_CONFLITONAOPERMITEAJUSTE_INCLUIR);

            }


            new ResourceAccess.Desconto().IncluirDesconto(request); 
        }



        /// <summary>
        /// Incluir Lista de Descontos
        /// </summary>
        /// <param name="requet"></param>
        public void IncluirDescontos(List<BusinessEntity.Desconto> requet)
        {
            foreach (BusinessEntity.Desconto item in requet)
            {
                IncluirDesconto(item);
            }
        }

        /// <summary>
        /// Retornar o Desconto para o filtro
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.Desconto ObterDesconto(BusinessEntity.Parameter.FiltroDesconto request)
        {
            return new ResourceAccess.Desconto().ObterDesconto(request); 
        }

        

        #region Validação

        /// <summary>
        /// Verificar se ocorre conflito
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public BusinessEntity.Conflito VerificarConflitoPeriodo(BusinessEntity.Desconto request)
        {
            BusinessEntity.Conflito retorno = new Sinacor.Servico.Bovespa.Corretagem.BusinessEntity.Conflito(); 
            List< BusinessEntity.Desconto>  listaDescontoConflito =  this.ConsultarConflitoPeriodo(request);
            if (listaDescontoConflito.Count == 0)
                retorno.ExisteConflito = false;
            else
            {
                DateTime dataIncialConflito = Convert.ToDateTime(listaDescontoConflito.Max(x => x.Periodo.DataInicial));
                if (dataIncialConflito > request.Periodo.DataInicial)
                {
                    retorno.ExisteConflito = true;
                    retorno.PermiteAjuste = false; 

                }
                else
                {
                    retorno.ExisteConflito = true;
                    retorno.PermiteAjuste = true;

                }
            }
            return retorno; 
        }
        /// <summary>
        /// Validar se os Parametros para Desconto são válidos
        /// </summary>
        /// <param name="entity"></param>
        private void ValidarDesconto(BusinessEntity.Desconto entity)
        {

            validarEntidadeDesconto(entity); 

            if (entity.Periodo.DataFinal < entity.Periodo.DataInicial)
                throw new ValidationException(ERRO_DATAFINALMAIORDATAINICIAL);

            if (entity.PercentualDescontoAcresimo < -100)
            {
                throw new ValidationException(ERRO_PERCENTUALACRESCIMO_MENOR);
            }
        }
        /// <summary>
        /// Validar RuleSets
        /// </summary>
        /// <param name="entity"></param>
        private void validarEntidadeDesconto(Sinacor.Servico.Bovespa.Corretagem.BusinessEntity.Desconto entity)
        {
            SinacorValidation validar = new SinacorValidation();
            validar.AddValidation<BusinessEntity.Periodo>(entity.Periodo, "CadastroDescontos"); 
            validar.AddValidation<BusinessEntity.Desconto>(entity);
            validar.Validate();
            validar = null; 
        }


        #endregion

        #region ConsultarDescontoPeriodo
        /// <summary>
        /// Task 6026 - LLiez.7Comm
        /// </summary>
        /// <param name="DataInicial"></param>
        /// <returns></returns>
        public List<BusinessEntity.Desconto> ConsultarDescontosPeriodo(DateTime DataInicial) 
        {
            return new ResourceAccess.Desconto().ConsultarDescontosPeriodo(DataInicial);
        }

        #endregion


        #region ValidarExistenciaDesconto
        public bool ValidarExistenciaDesconto(DateTime DataInicial) 
        {
            return (this.ConsultarDescontosPeriodo(DataInicial).Count > 0);
        }

        #endregion

        #endregion

    }
}
